package example.json.msg.service;

import net.sf.json.JSONObject;
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.*;
import org.apache.commons.httpclient.params.*;
import org.apache.log4j.Logger;
import java.io.IOException;
import java.net.ConnectException;

public class MsgHttpClient {

    private static final Logger LOG = Logger.getLogger(MsgHttpClient.class);

    private String url;

    private int conTimeOut = 30000;

    private int readTimeOut = 30000;

    private int retryCount = 3;

    public MsgHttpClient(String masterURL) {
        this.url = masterURL;
    }

    public MsgHttpClient(String masterURL, int retryCount) {
        this.url = masterURL;
        this.retryCount = retryCount;
    }

    /**
     * HTTP POST 请求
     * @param json 提交数据
     */
    public String doPostJson(JSONObject json, String encode){
        return doPostJson(json.toString(), encode);
    }

    public String doPostJson(JSONObject json){
        return doPostJson(json.toString(), "UTF-8");
    }

    private String doPostJson(String data, String encode){
        return doPostJson(data, false, encode);
    }

    private String doPostJson(String data, boolean isReconn, String encode) {
        String response = null;
        String requestURL = url;
        try {
            response = requestJson(requestURL, data);
        } catch (ConnectTimeoutException e) {
            redirectURLJson(data, isReconn, requestURL, encode, e);
        } catch (ConnectException ex) {
            redirectURLJson(data, isReconn, requestURL, encode, ex);
        } catch (Exception e) {
            LOG.error("访问：" + requestURL + " 异常:", e);
            System.err.println(e);
        }
        return response;
    }

    public String doPostParams(JSONObject json, String encode) {
        return doPostParams(json.toString(), encode);
    }

    public String doPostParams(JSONObject json) {
        return doPostParams(json.toString(), "UTF-8");
    }

    public String doPostParams(String data, String encode) {
        return doPostParams(data,false, encode);
    }

    private String doPostParams(String data, boolean isReconn, String encode) {
        String response = null;
        String requestURL = url;
        try {
            response = requestParams(requestURL, data, encode);
        } catch (ConnectTimeoutException e) {
            redirectURLParams(data, isReconn, requestURL, encode, e);
        } catch (ConnectException ex) {
            redirectURLParams(data, isReconn, requestURL, encode, ex);
        } catch (Exception e) {
            LOG.error("访问：" + requestURL + " 异常:", e);
            System.err.println(e);
        }
        return response;
    }


    private String requestParams(String url, String data, String encode) throws HttpException, IOException {
        String response = null;
        PostMethod postMethod = null;
        LOG.info("访问：" + url + " 请求数据:" + data);
        try {
            HttpClient client = new HttpClient(new HttpClientParams(), new SimpleHttpConnectionManager(true));
            postMethod = new PostMethod(url);
            postMethod.setRequestHeader("Connection", "close");
            postMethod.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, encode);
            JSONObject jo = JSONObject.fromObject(data);
            for(Object key : jo.keySet()) {
                postMethod.setParameter(key.toString(), jo.get(key).toString());
            }

            HttpConnectionManagerParams managerParams = client.getHttpConnectionManager().getParams();
            postMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler(getRetryCount(), false));
            managerParams.setConnectionTimeout(getConTimeOut());
            managerParams.setSoTimeout(getReadTimeOut());
            client.executeMethod(postMethod);
            if (postMethod.getStatusCode() == HttpStatus.SC_OK) {
                response = postMethod.getResponseBodyAsString();
                LOG.info("访问：" + url + " 响应数据:" + response);
            } else {
                LOG.error("访问：" + url + "异常，响应状态码：" + postMethod.getStatusCode() + ",响应内容：" + postMethod.getResponseBodyAsString());
            }
        } finally {
            if (postMethod != null)
                postMethod.releaseConnection();
        }
        return response;
    }

    private String requestJson(String url, String data) throws HttpException, IOException {
        String response = null;
        PostMethod postMethod = null;
        LOG.info("访问：" + url + " 请求数据:" + data);
        try {
            HttpClient client = new HttpClient(new HttpClientParams(), new SimpleHttpConnectionManager(true));
            postMethod = new PostMethod(url);
            postMethod.setRequestHeader("Connection", "close");
            postMethod.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "utf-8");
            byte[] byteData = data.getBytes("utf-8");
            RequestEntity requestEntity = new ByteArrayRequestEntity(byteData);
            postMethod.setRequestEntity(requestEntity);
            HttpConnectionManagerParams managerParams = client.getHttpConnectionManager().getParams();
            postMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler(retryCount, false));
            managerParams.setConnectionTimeout(conTimeOut);
            managerParams.setSoTimeout(readTimeOut);
            client.executeMethod(postMethod);
            if (postMethod.getStatusCode() == HttpStatus.SC_OK) {
                response = postMethod.getResponseBodyAsString();
                LOG.info("访问：" + url + " 响应数据:" + response);
            } else {
                LOG.error("访问：" + url + "异常，响应状态码：" + postMethod.getStatusCode() + ",响应内容：" + postMethod.getResponseBodyAsString());
            }
        } finally {
            if (postMethod != null)
                postMethod.releaseConnection();
        }
        return response;
    }

    private String redirectURLJson(String data, boolean isReconn, String lastRequestURL, String encode, Exception e) {
        if (!isReconn) {
            return doPostJson(data, true, encode);
        } else {
            LOG.error("访问：" + lastRequestURL + " 异常:", e);
        }
        return null;
    }

    private String redirectURLParams(String data, boolean isReconn, String lastRequestURL, String encode, Exception e) {
        if (!isReconn) {
            return doPostParams(data, true, encode);
        } else {
            LOG.error("访问：" + lastRequestURL + " 异常:", e);
        }
        return null;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public int getConTimeOut() {
        return conTimeOut;
    }

    public void setConTimeOut(int conTimeOut) {
        this.conTimeOut = conTimeOut;
    }

    public int getReadTimeOut() {
        return readTimeOut;
    }

    public void setReadTimeOut(int readTimeOut) {
        this.readTimeOut = readTimeOut;
    }

    public int getRetryCount() {
        return retryCount;
    }

    public void setRetryCount(int retryCount) {
        this.retryCount = retryCount;
    }
}
